#ifndef _TMC2660_H
#define _TMC2660_H

#include "user_global.h"

#define SPI_READ            1
#define SPI_WRITE           0
#define SPI_READ_MASK       0x8000
#define SPI_WRITE_MASK      0x8000
#define SPI_DATA_MASK       0x0FFF

#define SPI_BUF_SIZE       16     // 一定是2^n
#define SPI_BUF_MASK       (SPI_BUF_SIZE-1)

#define IO_SPI_CS(ch, v)            gpio_bit_write(spics_gport[ch].port, spics_gport[ch].pin, (FlagStatus)v)
#define IO_SPI_SELECT_NONE()        do{\
                                        IO_SPI_CS(0,0);\
                                        IO_SPI_CS(1,0);\
                                        IO_SPI_CS(2,0);\
                                        IO_SPI_CS(3,0);\
                                    }while(0)
#define IO_SPI_SELECT(ch)           do{\
                                        IO_SPI_SELECT_NONE();\
                                        IO_SPI_CS(ch,1);\
                                    } while(0)

#define DRVCTRL             0x00
#define TOUQUE              0x01
#define DECAY               0x04
#define CHOPCONF            0x00080000
#define SMARTEN             0X000A0000
#define SGCSCONF            0X000C0000
#define DRVCONF             0X000E0000

#define MICROSTEP16         0x04
#define MICROSTEP32         0x03
#define MICROSTEP64         0x02
#define MICROSTEP128        0x01
#define MICROSTEP256        0x00

#define DEFAULT_CURRENT     0x08

#define RSENSE              0.1f

#ifdef  USE_UP
#define S1_EXPECTED_WORK_CURRENT         3.000f
#else
#define S1_EXPECTED_WORK_CURRENT         1.000f
#endif

#define S1_EXPECTED_LOCK_CURRENT         0.150f

#define S2_EXPECTED_WORK_CURRENT         2.500f
#define S2_EXPECTED_LOCK_CURRENT         0.100f

#define S3_EXPECTED_WORK_CURRENT         3.000f
#define S3_EXPECTED_LOCK_CURRENT         0.100f

#define S4_EXPECTED_WORK_CURRENT         1.450f
#define S4_EXPECTED_LOCK_CURRENT         0.410f

#define TOUQUE_VALUE(ch, c)                  (((c) * 256 * (5.0*(reg_drvctrl[ch].isgain + 1)) * RSENSE)/2.75f)

#define DRV_COUNT       4

enum
{
    FORCE_SLOW_DECAY = 0,       // 000: Force slow decay at all times
    SLOW_DECAY_INCREASING = 1,  // 001: Slow decay for increasing current, mixed decay for decreasing current (indexer mode only)
    FORCE_FAST_DECAY = 2,       // 010: Force fast decay at all times
    MIXED_DECAY = 3,            // 011: Use mixed decay at all times
    SLOW_DECAY_AUTO_MIXED = 4,  // 100: Slow decay for increasing current, auto mixed decay for decreasing current (indexer mode only)
    AUTO_MIXED_DECAY = 5        // 101: Use auto mixed decay at all times
};

__packed typedef struct REG_DRVCTRL
{
    uchar enbl   : 1;
    uchar rdir   : 1;
    uchar rstep  : 1;
    uchar mode   : 4;
    uchar extall : 1;
    uchar isgain : 2;
    uchar dtime  : 2;
    uchar addr   : 3;
    uchar readwrite :1;
} REG_DRVCTRL;

extern REG_DRVCTRL reg_drvctrl[DRV_COUNT];

__packed typedef struct REG_TORQUE
{
    uchar torque   : 8;
    uchar smplth   : 3;
    uchar reserverd : 1;
    uchar addr   : 3;
    uchar readwrite :1;
} REG_TORQUE;

extern REG_TORQUE reg_torque[DRV_COUNT];

__packed typedef struct REG_DECAY
{
    uchar tdecay     : 8;
    uchar decmode    : 3;
    uchar reserverd  : 1;
    uchar addr   : 3;
    uchar readwrite :1;
} REG_DECAY;

extern REG_DECAY reg_decay[DRV_COUNT];

extern uchar  spi_rx_len;                                 // 已接收/或要发送长度
extern ushort  spi_rx_buf[SPI_BUF_SIZE];                  // spi发送/接收缓冲区
extern ulong  spi_timestamp;                              // 最后接收时间
extern ushort *spi_tx_ptr;                                // 发送指针
extern bit spi_rx_pending;                                // spi正在接收标志
extern bit spi_tx_pending;                                // spi正在发送标志
extern uchar  spi_tx_len;                                 // uart1要发送长度
extern ushort  spi_tx_buf[SPI_BUF_SIZE];                  // uart1发送缓冲区

// 通讯结果
#define SPI_RESULT_OK                             0
#define SPI_RESULT_TIMEOUT                        1
#define SPI_RESULT_CRC                            2
#define SPI_RESULT_EXCEPTION                      3

#define SPI_START()                               spi_tx_ptr = spi_tx_buf
#define SPI_APPEND(type, val)                     ((*(type *)&spi_tx_ptr[0])) = (val); spi_tx_ptr +=sizeof(type)
#define SPI_END()                                 spi_tx_len = (spi_tx_ptr - spi_tx_buf)/2

void TmcInit(void);
void Set_Tmc_Current(uchar value);
void Drv_Init(uchar role);
bit Spi_WriteRead(uchar ch, ushort*write, ushort *read, uchar size);
void Drv_Work_Full(uchar role);
void Drv_Work_Lock(uchar role);
void Drv_Disable(uchar role);
void Drv_Set_Decay(uchar role);

#endif  //_TMC2660_H
